// Copyright (c) 2025 Huawei Technologies Co., Ltd.
// openUBMC is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//         http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
//
// Description: 封装和解析KVM消息报文

#include "KVMMessage.hpp"

const int HEADER_LEN = 8;

KVMMessage::KVMMessage() = default;

KVMMessage::~KVMMessage() = default;

std::vector<uint8_t> KVMMessage::Pack(uint16_t kvmCmdType, int bladeId, const std::vector<uint8_t>& data) {
    const size_t totalLength = HEADER_LEN + data.size();
    std::vector<uint8_t> packData(totalLength);

    int length = data.size();

    packData[0] = static_cast<uint8_t> ((length & 0xff000000) >> 24);       // 消息长度4字节的高8位
    packData[1] = static_cast<uint8_t> ((length & 0x00ff0000) >> 16);       // 消息长度4字节的次高8位
    packData[2] = static_cast<uint8_t> ((length & 0x0000ff00) >> 8);        // 消息长度4字节的次低8位
    packData[3] = static_cast<uint8_t> (length & 0x000000ff);               // 消息长度4字节的低8位
    packData[4] = static_cast<uint8_t> ((kvmCmdType & 0xff00) >> 8);        // KVM消息类型2字节的高8位
    packData[5] = static_cast<uint8_t> (kvmCmdType);                        // KVM消息类型2字节的低8位
    packData[6] = static_cast<uint8_t> (bladeId & 0xff);                    // blade ID 1字节
    packData[7] = static_cast<uint8_t> (0xff);                              // 保留字段1字节

    if (!data.empty()) {
        std::copy(data.begin(), data.end(), packData.begin() + HEADER_LEN);
    }
    return packData;
}

bool KVMMessage::Unpack(const std::string& data) {
    if (data.length() < HEADER_LEN) {
        std::cerr << "Invalid packet data length: " << data.length() << std::endl;
        return false;
    }

    // 按照big-endian解析报文头
    // 前4字节表示消息长度
    length_ = (static_cast<uint8_t>(data[0]) << 24) |           // 消息长度4字节的高8位
             (static_cast<uint8_t>(data[1]) << 16) |            // 消息长度4字节的次高8位
             (static_cast<uint8_t>(data[2]) << 8) |             // 消息长度4字节的次低8位
             static_cast<uint8_t>(data[3]);                     // 消息长度4字节的低8位
    
    // 接下来的2字节表示KVM消息类型
    cmdType_ = (static_cast<uint8_t>(data[4]) << 8) | static_cast<uint8_t>(data[5]);
    // 接下来的1字节表示blade ID
    bladeId_ = static_cast<uint8_t>(data[6]);
    // 最后1字节表示保留字段
    reserved_ = static_cast<uint8_t>(data[7]);

    // 检查报文长度是否匹配
    if (length_ != data.length() - HEADER_LEN) {
        std::cerr << "Body length mismatch: expected " << length_ << ", got " << data.length() - HEADER_LEN << std::endl;
        return false;
    }

    // 设置报文体
    body_.assign(data.begin() + HEADER_LEN, data.end());
    return true;
}

uint16_t KVMMessage::GetCmdType() const {
    return cmdType_;
}

uint8_t KVMMessage::GetBladeId() const {
    return bladeId_;
}

std::vector<uint8_t> KVMMessage::GetBody() const {
    return body_;
}